package testTransfoUML2Java;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Iterator;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import uml2Java.JavaChargeur;
import uml2Java.TransformAttributes;
import uml2Java.TransformPackagesAndTypes;
import uml2Java.UMLChargeur;
import astjava.AbstractTypeDeclaration;
import astjava.BodyDeclaration;
import astjava.ClassDeclaration;
import astjava.EnumDeclaration;
import astjava.FieldDeclaration;
import astjava.InterfaceDeclaration;
import astjava.JavaFactory;
import astjava.MethodDeclaration;

public class TestTransformAttributes {
	
	private static org.eclipse.uml2.uml.Package _umlPackage;
	
	private static astjava.Model _javaModel;
	
	private static TransformPackagesAndTypes _transformerTypes;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		_javaModel = JavaFactory.eINSTANCE.createModel();
		UMLChargeur chargeur = new UMLChargeur("modele_de_test/testAttributes.uml");
		_umlPackage = chargeur.loadUMLPackage();
		
		_transformerTypes = new TransformPackagesAndTypes(_umlPackage, _javaModel);
		_transformerTypes.doTransformPackagesAndTypes();
		TransformAttributes transformerAttributes = new TransformAttributes(_transformerTypes);
		transformerAttributes.doTransformAttributes();
	}
	
	@Test
	public void testLiteralsEnum() {
		EList<AbstractTypeDeclaration> types = _javaModel.getOwnedElements().get(0).getOwnedElements();
		for (AbstractTypeDeclaration type : types) {
			if (type instanceof EnumDeclaration) {
				EnumDeclaration enumDec = (EnumDeclaration) type;
				if (enumDec.getName().equals("EnumerationPublic")) {
					assertTrue(enumDec.getEnumConstants().size()==2);
				}
				if (enumDec.getName().equals("EnumerationPackage")) {
					assertTrue(enumDec.getEnumConstants().size()==2);
				}
			}
		}
	}
	
	@Test
	public void testAttributesInterface() {
		EList<AbstractTypeDeclaration> types = _javaModel.getOwnedElements().get(0).getOwnedElements();
		for (AbstractTypeDeclaration type : types) {
			if (type instanceof InterfaceDeclaration) {
				InterfaceDeclaration interfaceDec = (InterfaceDeclaration) type;
				if (interfaceDec.getName().equals("InterfacePublic")) {
					assertTrue(interfaceDec.getBodyDeclarations().size()==2);
				}
			}
		}
	}
	
	@Test
	public void testAttributesClass() {
		EList<AbstractTypeDeclaration> types = _javaModel.getOwnedElements().get(0).getOwnedElements();
		for (AbstractTypeDeclaration type : types) {
			if (type instanceof ClassDeclaration) {
				ClassDeclaration classDec = (ClassDeclaration) type;
				if (classDec.getName().equals("ClassPackage")) {
					assertTrue(classDec.getBodyDeclarations().size()==9);
				}
				if (classDec.getName().equals("ClassDataType")) {
					assertTrue(classDec.getBodyDeclarations().size()==1);
				}
			}
		}
	}
	
	@Test
	public void testAttributesType() {
		for (Type umlType : _umlPackage.getOwnedTypes()) {
			if (umlType instanceof Class || umlType instanceof Interface) {
				Classifier umlClassifier = (Classifier) umlType;
				astjava.AbstractTypeDeclaration javaType = (AbstractTypeDeclaration) _transformerTypes.get_symbolMap().get(umlClassifier.getName());
				EList<Property> umlAttributes = umlClassifier.getAttributes();
				EList<BodyDeclaration> javaAttributes = javaType.getBodyDeclarations();
				Iterator<Property> iUmlAttributes = umlAttributes.iterator();
				Iterator<BodyDeclaration> iJavaAttributes = javaAttributes.iterator();
				while (iUmlAttributes.hasNext()) {
					Property umlAttribute = iUmlAttributes.next();
					BodyDeclaration javaBodyDeclaration = iJavaAttributes.next();
					if (javaBodyDeclaration instanceof FieldDeclaration) {
						FieldDeclaration javaAttribute = (FieldDeclaration) javaBodyDeclaration;
						assertEquals(_transformerTypes.get_symbolMap().get(umlAttribute.getType().getName()), javaAttribute.getType().getType());
					}
				}
			}
		}
	}
	
	@Test
	public void testAccessorsOnAttribute() {
		ClassDeclaration javaClass = (ClassDeclaration) _transformerTypes.get_symbolMap().get("ClassPublic");
		EList<MethodDeclaration> accesseurs = new BasicEList<MethodDeclaration>();
		for (BodyDeclaration bodyDeclaration : javaClass.getBodyDeclarations()) {
			if (bodyDeclaration instanceof MethodDeclaration) {
				accesseurs.add((MethodDeclaration) bodyDeclaration);
			}
		}
		assertTrue(accesseurs.size()==2);
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		JavaChargeur chargeur = new JavaChargeur("modele_de_test/testAttributes.astjava");
		chargeur.save(_javaModel);
	}

}
